#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include "capaFuse.h"
#include <signal.h>
#include "log.h"

static struct fuse_operations hello_oper = {
    .getattr  = hello_getattr,  //Funciona(stat)
    .readdir  = hello_readdir,	//Funciona(ls)
    .open     = hello_open,		//Funciona
    .read     = hello_read,		//Funciona
    .rename   = hello_rename,	//Funciona(mv)
    .truncate = hello_truncate,	//Funciona(truncate)
    .mkdir    = hello_mkdir,	//Funciona(mkdir)
    .unlink   = hello_unlink,	//Funciona(unlink)
    .rmdir    = hello_rmdir,	//Funciona(rmdir)
    .flush    = hello_flush,	//Funciona
    .write    = hello_write,	//Funciona
    .create   = hello_create,	//Funciona(touch)
    .release  = hello_release	//Funciona
};

void* fs_Consola();
void* fs_fuse();
void evaluarComando(char *comando);
void inicializaciones();

Boot_Sector BootSector;
Fat FAT;
t_list *fileOpenTable;
tipoConfigPFS configPFS;
t_log *archLog;
sem_t fatSemaforo;
sem_t cacheSemaforo;
sem_t poolSemaforo;
sem_t poolMutex;
conexion *poolDeConexiones;

/*----------------------------------------main----------------------------------------*/
int main(int argc, char **argv) {
	//-------------------------
	inicializaciones(); //FAT, BootSector, configPFS, semaforos, fileOpenTable
	//-------------------------
	int ret1;
	pthread_t tidConsola;
	ret1 = pthread_create(&tidConsola, NULL, fs_Consola, NULL);
	//-------------------------
	fuse_main(argc, argv, &hello_oper, NULL);

	return 0;
}
/*----------------------------------------main----------------------------------------*/

void inicializaciones() {
	configPFS = leerArchConfigPFS();
	sem_init(&fatSemaforo, 0, 1);
	sem_init(&cacheSemaforo, 0, 1);
	sem_init(&poolSemaforo, 0, configPFS.maxCon);
	sem_init(&poolMutex, 0, 1);
	poolDeConexiones = malloc(configPFS.maxCon*sizeof(conexion));
	memset(poolDeConexiones, 0, configPFS.maxCon*sizeof(conexion));
	if(crearPoolDeConexiones(configPFS.puerto,configPFS.ip)==-1)
		perror("error en conexion");
	BootSector = fat32_LeerBootSector();
	FAT.tabla = malloc(8192);
	FAT.bitDeUso = noModificado;
	fat32_LeerFatRegion(0);
	fileOpenTable = collection_list_create();
	archLog = log_create("FileSystem", configPFS.logArchPath, 8, 1);
	signal(SIGUSR1, cacheDump);
}

void* fs_Consola(void* arg) {
	char *comando = malloc(40);
	while (1) {
		printf("ingrese un comando: ");
		comando = gets(comando);
		evaluarComando(comando);
		printf("\n");
	}
	return 0;
}

void evaluarComando(char *comando) {
	uint32_t i, posicionFAT, clusterLibres, clusterOcupados, clusterTotal;
	infoDir info;

	if (!strcmp(comando, "fsinfo")) {
		clusterLibres = fat32_ObtenerClustersLibres();
		clusterTotal = (BootSector.secPerFat * 512) / 4 + (BootSector.rsvdSecCnt) / (BootSector.secPerClus)
				     + (BootSector.secPerFat * BootSector.numFats)/BootSector.secPerClus;
		clusterOcupados = clusterTotal - clusterLibres;
		printf("La cantidad de cluster ocupados son: %d\n", clusterOcupados);
		printf("La cantidad de cluster libres son: %d\n", clusterLibres);
		printf("El tamaño de un sector es de: %d B\n", BootSector.bytesPerSec);
		printf("El tamaño de un cluster es de: %d B\n", BootSector.bytesPerSec
				* BootSector.secPerClus);
		printf("El tamaño de la FAT es de: %d KB\n", (BootSector.bytesPerSec
				* BootSector.secPerFat) / 1024);
	} else {
		if (!strncmp(comando, "finfo", 5)) {
			printf("Path: %s\n", comando + 6);

			if (*(comando + 6) != '/') {
				printf("Path no encontrado\n");
				return;
			}
			info = buscar(comando + 6);
			if (info.resultadoBusqueda == noEncontrado) {
				printf("Path no encontrado\n");
				return;
			}
			if(info.clusterContenido==0){
				printf("El archivo no tiene clusters asociados\n");
				return;
			}
			posicionFAT = info.clusterContenido;
			printf("#Clusters:\n[%d", posicionFAT);
			if (!fat32_SeEncuentraEnTabla(posicionFAT))
				fat32_LeerFatRegion(posicionFAT);
			for (i = 1; i < 20 ; i++) {
				posicionFAT = fat32_SiguienteCadenaFat(posicionFAT);
				if(!fat32_esFinDeCadena(posicionFAT))
					printf(", %d", posicionFAT);
				else
					break;
			};
			printf("]\n");
		} else
			printf("Comando erroneo\n");
	}
}
